package com.dic.common.base.dao.impl;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import com.dic.common.utils.helper.Pager;
import org.hibernate.criterion.Order;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.Query;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Repository;

import com.dic.common.base.dao.IBaseDao;

@Repository
public class BaseDaoImpl implements IBaseDao{

	@PersistenceContext
	private EntityManager entityManager; 
	
	public CriteriaBuilder getCriteriaBuilder() {
		return entityManager.getCriteriaBuilder();
	}
	
	@Override
	public boolean save(Object entity) {
		boolean flag = false;
		try {
			entityManager.persist(entity);
			flag = true;
		} catch (Exception e) {
			System.out.println("---------------保存出错---------------");
            throw e;
		}
		return flag;
	}
	
	@Override
	public boolean update(Object entity) {
		boolean flag = false;
		try {
			entityManager.merge(entity);
			flag = true;
		} catch (Exception e) {
			System.out.println("---------------更新出错---------------");
			throw e;
		}
		return flag;
	}
	
	@Override
	public boolean delete(Object entity) {
		boolean flag = false;
		try {
			entityManager.remove(entity);
			flag = true;
		} catch (Exception e) {
			System.out.println("---------------删除出错---------------");
			throw e;
		}
		return flag;
	}
	
	@Override
	public <T> T getEntityById(Class<T> objClass, String id) {
		return entityManager.find(objClass, id);
	}
	
	@Override
	public <T> List<T> queryAll(Class<T> objClass, Order order) {
		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<T> criteriaQuery = cb.createQuery(objClass);
        Root<T> root = criteriaQuery.from(objClass);
        if(order!=null) {//排序
			List<javax.persistence.criteria.Order> orders = new ArrayList<javax.persistence.criteria.Order>(); 
			if (order.ignoreCase().toString().indexOf("asc")>0)  
				orders.add(cb.asc(root.get(order.getPropertyName())));  
			else
				orders.add(cb.desc(root.get(order.getPropertyName()))); 
			criteriaQuery.orderBy(orders);
		}
        TypedQuery<T> typedQuery = entityManager.createQuery(criteriaQuery);
        return typedQuery.getResultList();
	}
	
	@Override
	public <T> List<T> queryEntity(CriteriaQuery<T> criteriaQuery, Root<T> root, List<Predicate> predicates, Order order){
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));//查询条件
		if(order!=null) {//排序
			List<javax.persistence.criteria.Order> orders = new ArrayList<javax.persistence.criteria.Order>(); 
			if (order.ignoreCase().toString().indexOf("asc")>0)  
				orders.add(criteriaBuilder.asc(root.get(order.getPropertyName())));  
			else
				orders.add(criteriaBuilder.desc(root.get(order.getPropertyName()))); 
			criteriaQuery.orderBy(orders);
		}
		return entityManager.createQuery(criteriaQuery).getResultList();
	}
	
	@Override
	public <T>Pager<T> queryPage(int page, int rows, CriteriaQuery<T> criteriaQuery, Root<T> root, List<Predicate> predicates, Order order, Class<T> objClass) {
		Pager<T> pager = null;  
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));
		if(order!=null) {//排序
			List<javax.persistence.criteria.Order> orders = new ArrayList<javax.persistence.criteria.Order>(); 
			if (order.ignoreCase().toString().indexOf("asc")>0)  
				orders.add(criteriaBuilder.asc(root.get(order.getPropertyName())));  
			else
				orders.add(criteriaBuilder.desc(root.get(order.getPropertyName()))); 
			criteriaQuery.orderBy(orders);
		}
		List<T> result = entityManager.createQuery(criteriaQuery).setFirstResult((page-1)*rows).setMaxResults(rows).getResultList(); 
    	//查询总条数
		long rowCount = entityManager.createQuery(criteriaQuery).getResultList().size(); 
		long pageCount = (rowCount%rows==0)?rowCount/rows:(rowCount/rows+1); //总页数
		pager = new Pager<T>(pageCount,rowCount, result);  
	    return pager;  
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> queryHQL(String HQL, Map<String,String> attributeMap, Class<T> objClass){
		Query<T> query = null;
		if(objClass==null)
			query = (Query<T>) entityManager.createQuery(HQL);
		else
			query = (Query<T>) entityManager.createQuery(HQL, objClass);
		if(attributeMap!=null && !attributeMap.isEmpty()){	
			for(String key:attributeMap.keySet()) {
				query.setParameter(key, attributeMap.get(key));
			}
		}
		return (List<T>)query.list();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <T> Pager<T> queryHQLPage(int page, int rows, String HQL, Map<String,String> attributeMap, Class<T> objClass) {
		Query<T> query = null;
		if(objClass==null)
			query = (Query<T>)entityManager.createQuery(HQL);
		else
			query = (Query<T>)entityManager.createQuery(HQL, objClass);
		String countHql = "select count(*) "+HQL; //查询总记录条数
		Query<Long> queryCount = (Query<Long>) entityManager.createQuery(countHql); 
		if(attributeMap!=null && !attributeMap.isEmpty()){	
			for(String key:attributeMap.keySet()) {
				query.setParameter(key, attributeMap.get(key));
				queryCount.setParameter(key, attributeMap.get(key));
			}
		}
		query.setFirstResult((page-1)*rows); 
		query.setMaxResults(rows); 
		List<T> list= (List<T>)query.setCacheable(true).getResultList();
		long rowCount = (Long)queryCount.uniqueResult();
		long pageCount = (rowCount%rows==0)?rowCount/rows:(rowCount/rows+1); //总页数
		Pager<T> pager = new Pager<T>(pageCount,rowCount,list);  
		return pager;
	}
	
	
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> querySQL(String SQL, List<Object> attributeList, Class<T> objClass) {
		Query<T> sqlQuery = null;
		if(objClass==null)
			sqlQuery = (Query<T>) entityManager.createNativeQuery(SQL);
		else
			sqlQuery = (Query<T>) entityManager.createNativeQuery(SQL, objClass);
		if(attributeList!=null && !attributeList.isEmpty()){
			for (int i = 0, size = attributeList.size(); i < size; i++) {
				sqlQuery.setParameter(i+1, attributeList.get(i));
			}
		}
		return (List<T>)sqlQuery.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> querySQL(String SQL, Map<String,String> attributeMap, Class<T> objClass) {
		Query<T> sqlQuery = null;
		if(objClass==null)
			sqlQuery = (Query<T>) entityManager.createNativeQuery(SQL);
		else
			sqlQuery = (Query<T>) entityManager.createNativeQuery(SQL, objClass);
		if(attributeMap!=null && !attributeMap.isEmpty()){	
			for(String key:attributeMap.keySet()) {
				System.out.println(key+" = "+attributeMap.get(key));
				sqlQuery.setParameter(key, attributeMap.get(key));
			}
		}
		return (List<T>)sqlQuery.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <T>Pager<T> querySQLPage(int page, int rows, String SQL, List<Object> attributeList, Class<T> objClass) {
		Query<T> sqlQuery = null;
		if(objClass==null)
			sqlQuery = (Query<T>) entityManager.createNativeQuery(SQL);
		else
			sqlQuery = (Query<T>) entityManager.createNativeQuery(SQL,objClass);
		String countSql = "select count(*) from ("+SQL+") as t"; //查询总记录条数
		Query<T> sqlQueryCount = (Query<T>) entityManager.createNativeQuery(countSql); 
		if(attributeList!=null && !attributeList.isEmpty()){
			for (int i = 0, size = attributeList.size(); i < size; i++) {
				sqlQuery.setParameter(i+1, attributeList.get(i));
				sqlQueryCount.setParameter(i+1, attributeList.get(i));//查询条数
			}
		}
		sqlQuery.setFirstResult((page-1)*rows); 
		sqlQuery.setMaxResults(rows); 
		List<T> list= (List<T>)sqlQuery.list();
		BigInteger rowCountBig = (BigInteger)sqlQueryCount.uniqueResult();
		long rowCount = rowCountBig.longValue();
		long pageCount = (rowCount%rows==0)?rowCount/rows:(rowCount/rows+1); //总页数
		Pager<T> pager = new Pager<T>(pageCount,rowCount,list);  			
		return pager;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <T>Pager<T> querySQLPage(int page, int rows, String SQL, Map<String,String> attributeMap, Class<T> objClass) {
		Query<T> sqlQuery = null;
		if(objClass==null)
			sqlQuery = (Query<T>) entityManager.createNativeQuery(SQL);
		else
			sqlQuery = (Query<T>) entityManager.createNativeQuery(SQL,objClass);
		String countSql = "select count(*) from ("+SQL+") as t"; //查询总记录条数
		Query<T> sqlQueryCount = (Query<T>) entityManager.createNativeQuery(countSql); 
		if(attributeMap!=null && !attributeMap.isEmpty()){
			for (String key : attributeMap.keySet()) {
				sqlQuery.setParameter(key, attributeMap.get(key));
				sqlQueryCount.setParameter(key, attributeMap.get(key));//查询条数
			}
		}
		sqlQuery.setFirstResult((page-1)*rows); 
		sqlQuery.setMaxResults(rows); 
		List<T> list= (List<T>)sqlQuery.list();
		BigInteger rowCountBig = (BigInteger)sqlQueryCount.uniqueResult();
		long rowCount = rowCountBig.longValue();
		long pageCount = (rowCount%rows==0)?rowCount/rows:(rowCount/rows+1); //总页数
		Pager<T> pager = new Pager<T>(pageCount,rowCount,list);  			
		return pager;
	}
	
	@Override
	public int executeHQL(String HQL, List<Object> attributeList) {
		Query<?> query = (Query<?>) entityManager.createQuery(HQL);
		if(attributeList!=null && !attributeList.isEmpty()){
			for (int i = 0, size = attributeList.size(); i < size; i++) {
				query.setParameter(i, attributeList.get(i));
			}
		}
		return query.executeUpdate();
	}
	
	@Override
	public int executeHQL(String HQL, Map<String,String> attributeMap) {
		Query<?> query = (Query<?>) entityManager.createQuery(HQL);
		if(attributeMap!=null && !attributeMap.isEmpty()){
			for (String key : attributeMap.keySet()) {
				query.setParameter(key, attributeMap.get(key));
			}
		}
		return query.executeUpdate();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<Object[]> queryBySql(String SQL) {    
		return entityManager.createNativeQuery(SQL).getResultList();    
	}   
	
	@SuppressWarnings({ "deprecation", "unchecked" })
	@Override
	public List<Map<String,Object>> queryBySqlM(String SQL) {  
		Query<?> query = (Query<?>) entityManager.createNativeQuery(SQL);
		query.unwrap(NativeQueryImpl.class);
		query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		return (List<Map<String, Object>>) query.getResultList();
	}
	
	@Override
	public int executeSql(String SQL,List<Object> attributeList){    
		NativeQuery<?> query = (NativeQuery<?>) entityManager.createNativeQuery(SQL);
		if(attributeList!=null && !attributeList.isEmpty()){
			for (int i = 0, size = attributeList.size(); i < size; i++) {
				query.setParameter(i, attributeList.get(i));
			}
		}
		return query.executeUpdate();    
    }
	
	@Override
	public int executeSql(String SQL,Map<String,String> attributeMap){    
		NativeQuery<?> query = (NativeQuery<?>) entityManager.createNativeQuery(SQL);
		if(attributeMap!=null && !attributeMap.isEmpty()){
			for (String key : attributeMap.keySet()) {
				query.setParameter(key, attributeMap.get(key));
			}
		}
		return query.executeUpdate();    
    }
	
}
